/* 
 * File:   Perimetro.cpp
 * Author: 75.02 - Grupo 7, 2do cuatrimestre 2012.
 * 
 * Created on November 3, 2012, 7:44 PM
 */

#include <sstream>
#include "Perimetro.h"
#include "UtilidadesConstantes.h"
using namespace TP::Juego::Arena::Utilidades;

Perimetro::Perimetro() : Utilidad ("", new Rol (PERIMETRO, PERIMETRO)){
    
    this->_alto = 0;
    this->_ancho = 0;
}

Perimetro::Perimetro(const string& pNombre, unsigned long int pAlto, unsigned long int pAncho) : Utilidad (pNombre, new Rol (PERIMETRO, PERIMETRO)){
    
    this->_alto = pAlto;
    this->_ancho = pAncho;
}

Perimetro::~Perimetro() {}

unsigned long int Perimetro::getAlto(){
    return this->_alto;
}

unsigned long int Perimetro::getAncho(){
    return this->_ancho;
}

bool Perimetro::pertenecePerimetro (Posicion* pPosicion){
    
    bool pertenece = false;
    
    if (pPosicion)
    {
        pertenece = true;
        pertenece = pertenece && (pPosicion->X() > 0);
        pertenece = pertenece && (pPosicion->X() < this->getAncho() - 1);
        pertenece = pertenece && (pPosicion->Y() > 0);
        pertenece = pertenece && (pPosicion->Y() < this->getAlto() - 1);
    }
    
    return pertenece;
}

Vector2D* Perimetro::getNormalAPuntoPerimetro (Posicion* pPosicion){
    
    // Por default, la posicion no corresponde a un punto del perimetro.
    // Por ende, no tiene una normal definida.

    Vector2D* normal = new Vector2D(0,0);
    
    if (pPosicion->X() == 0)
    {
        normal->X(1);
        
        if (pPosicion->Y() == 0)
            normal->Y(1);

        else if (pPosicion->Y() == this->getAlto() - 1)
            normal->Y(-1);

        else
            normal->Y(0);
    }
    else if (pPosicion->X() == this->getAncho() -1)
    {
        normal->X(-1);
        
        if (pPosicion->Y() == 0)
            normal->Y(1);

        else if (pPosicion->Y() == this->getAlto() - 1)
            normal->Y(-1);

        else
            normal->Y(0);
    }
    else if (pPosicion->Y() == 0)
    {
        normal->Y(1);
        
        if (pPosicion->X() == 0)
            normal->X(1);
        else if (pPosicion->X() == this->getAncho() -1)
            normal->X(-1);
        else
            normal->X(0);
    }
    else if (pPosicion->Y() == this->getAlto() - 1)
    {
        normal->Y(-1);
        
        if (pPosicion->X() == 0)
            normal->X(1);
        else if (pPosicion->X() == this->getAncho() -1)
            normal->X(-1);
        else
            normal->X(0);
    }
    
    return normal;
}

Vector2D* Perimetro::getPuntoAdjuntoInterior (Posicion* pPosicion){
 
    Vector2D* interior = new Vector2D (0,0);
    
    if (pPosicion->X() == 0)
    {
        interior->X(1);
        
        if (pPosicion->Y() == 0)
            interior->Y(1);

        else if (pPosicion->Y() == this->getAlto() - 1)
            interior->Y(-1);

        else
            interior->Y(pPosicion->Y());
    }
    else if (pPosicion->X() == this->getAncho() -1)
    {
        interior->X(-1);
        
        if (pPosicion->Y() == 0)
            interior->Y(1);

        else if (pPosicion->Y() == this->getAlto() - 1)
            interior->Y(-1);

        else
            interior->Y(pPosicion->Y());
    }
    else if (pPosicion->Y() == 0)
    {
        interior->Y(1);
        
        if (pPosicion->X() == 0)
            interior->X(1);
        else if (pPosicion->X() == this->getAncho() -1)
            interior->X(-1);
        else
            interior->X(pPosicion->X());
    }
    else if (pPosicion->Y() == this->getAlto() - 1)
    {
        interior->Y(-1);
        
        if (pPosicion->X() == 0)
            interior->X(1);
        else if (pPosicion->X() == this->getAncho() -1)
            interior->X(-1);
        else
            interior->X(pPosicion->X());
    }
    
    return interior;    
}

string Perimetro::aXML(){

    TiXmlDocument* doc = new TiXmlDocument();
    TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
    doc->LinkEndChild( decl );
    
    doc->LinkEndChild(this->aElementoXML());

    TiXmlPrinter printer;
    doc->Accept(&printer);
    return printer.CStr();    
}

string Perimetro::aXML(const string& pPath){

    TiXmlDocument* doc = new TiXmlDocument(pPath.c_str());
    TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
    doc->LinkEndChild( decl );
    
    doc->LinkEndChild(this->aElementoXML());
    
    TiXmlPrinter printer;
    doc->Accept(&printer);
    return printer.CStr();    
}

void Perimetro::parseXML (const string& pDescriptor){

    TiXmlDocument doc;
    doc.Parse(pDescriptor.c_str(), 0, TIXML_ENCODING_UTF8);
    this->deElementoXML(doc.FirstChildElement());
}

TiXmlElement* Perimetro::aElementoXML (){
    
    TiXmlElement * element = new TiXmlElement(PERIMETRO);

    element->SetAttribute("nombre", this->getNombre().c_str());
    
    std::stringstream stream;
    stream << this->_alto;
    element->SetAttribute("alto", stream.str().c_str());  
    
    stream.str(std::string());
    stream << this->_ancho;
    element->SetAttribute("ancho", stream.str().c_str());  
    
    return element;
}

void Perimetro::deElementoXML (TiXmlElement* pElemento){

    if (strcmp (pElemento->Value(), PERIMETRO) == 0)
    {
        this->setNombre(pElemento->Attribute("nombre"));
        std::stringstream (pElemento->Attribute("alto")) >> this->_alto;
        std::stringstream (pElemento->Attribute("ancho")) >> this->_ancho;
    }
}

